﻿using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
using static FinalPointSet.Model.Util.ScreenUtil;

namespace FinalPointSet.Model.Util
{
    /// <summary>
    /// 屏幕工具类
    /// </summary>
    public class ScreenUtil
    {
        #region Win32方法
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern bool GetCursorPos(out POINT lpPoint);

        [DllImport("user32.dll")]
        private static extern IntPtr WindowFromPoint(POINT Point);

        [DllImport("user32.dll")]
        private static extern uint GetDpiForWindow(IntPtr hWnd);

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int X;
            public int Y;
        }
        #endregion


        /// <summary>
        /// 获取鼠标位于的窗口的DPI
        /// </summary>
        /// <returns></returns>
        public static Dpi? GetDpiFromMouse()
        {
            Dpi? dpi = null;
            if (GetCursorPos(out POINT p))
            {
                IntPtr hWnd = WindowFromPoint(p);
                if (hWnd != IntPtr.Zero)
                {
                    uint udpi = GetDpiForWindow(hWnd);
                    dpi = new Dpi((double)udpi / 96, (double)udpi / 96); // 这里实际上可以直接返回 dpi 值，但为了与你的 Dpi 类兼容，我们进行了转换
                                                                         // 注意：在某些情况下，GetDpiForWindow 可能返回的是每英寸点数（DPI）的整数倍，因此你可能需要对结果进行舍入或调整。
                                                                         // 另外，如果你的应用程序在高 DPI 感知模式下运行，并且用户已经调整了缩放设置，那么 GetDpiForWindow 返回的 DPI 值将反映这些设置。
                }
            }

            // 如果无法获取鼠标所在屏幕的 DPI，则返回一个默认值（例如系统默认 DPI）
            return dpi;
        }

        public static Screen GetScreenFromMousePosition()
        {
            // 获取鼠标的位置（Point 类型为 WPF 中的结构）
            Point mousePosition = GetMousePositionOnScreen();

            // 将 WPF 的 Point 转换为 Windows Forms 的 Point
            var winFormsPoint = new System.Drawing.Point((int)mousePosition.X, (int)mousePosition.Y);

            // 获取所有屏幕
            Screen[] screens = Screen.AllScreens;

            // 遍历所有屏幕，找到鼠标所在的屏幕
            return screens.FirstOrDefault(s => s.Bounds.Contains(winFormsPoint)) ?? screens[0]; // 如果没有找到，则返回第一个屏幕
        }

        /// <summary>
        /// 获取窗体位于的窗体
        /// </summary>
        /// <param name="window"></param>
        /// <returns></returns>
        public static Screen GetScreenFromWindowPosition(Window window)
        {
            Point location = window.PointToScreen(new Point(window.Width / 2, window.Height / 2));
            return Screen.FromPoint(MethodUtil.PointFormat(location));
        }

        /// <summary>
        /// 获取当前的主屏幕
        /// </summary>
        /// <returns></returns>
        public static Screen GetPrimaryScreen()
        {
            return Screen.PrimaryScreen ?? Screen.AllScreens[0];
        }

        /// <summary>
        /// 获取当前鼠标坐标
        /// </summary>
        /// <returns></returns>
        public static Point GetMousePositionOnScreen()
        {
            var cursorPos = Cursor.Position;
            return new Point(cursorPos.X, cursorPos.Y);
        }

        /// <summary>
        /// 获取当前窗体的DPI
        /// </summary>
        /// <param name="compositionTarget"></param>
        /// <returns></returns>
        public static Dpi? GetDpi(Window window)
        {
            var compositionTarget = PresentationSource.FromVisual(window)?.CompositionTarget;
            if (compositionTarget == null)
            {
                return null;
            }

            Matrix matrix = compositionTarget.TransformToDevice;

            double dpiX = matrix.M11;
            double dpiY = matrix.M22;

            return new Dpi(dpiX, dpiY);
        }

        public class Dpi
        {
            /// <summary>
            /// 横向比例
            /// </summary>
            public double X { get; }
            /// <summary>
            /// 纵向比例
            /// </summary>
            public double Y { get; }

            public Dpi(double x, double y)
            {
                X = x;
                Y = y;
            }

            public override string ToString()
            {
                return $"{X}x{Y}";
            }
        }
    }
}
